package com.zsr.xmall.search.thread;

import java.util.concurrent.*;

/**
 * 多线程测试类
 */
public class ThreadTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1.测试callable，配合FutureTask（本质也是runnable）
        FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());// 【new FutureTask<>(new MyRunnable(), result)】可以接受runnable的返回值
        new Thread(futureTask).start();
        //System.out.println(futureTask.get());// 阻塞等待异步执行结束获取结果

        // 2.创建一个固定线程数的线程池，执行异步任务
        ExecutorService pool = Executors.newFixedThreadPool(10);// 使用了线程池，所以当前程序不会结束
        Future<?> future = pool.submit(new MyCallable());
        System.out.println("future: " + future.get());

        /**
         * 工作顺序
         * 1) 线程池创建，准备好core数量的核心线程，准备接收任务
         * 1.1、core满了，就将再进来的任务放到阻塞队列中。空闲的core就会自己去阻塞队列中获取任务执行
         * 1.2、阻塞队列满了，就直接开新线程执行，最大只能开到max指定的数量
         * 1.3、max满了就用拒绝策略 拒绝任务
         * 1.4、max都执行完成，就有很多空闲，在指定的时间keepAliveTime以后。再释放 max 减 code 数量的线程
         *
         *      堵塞队列 new LinkedBlockingDeque<>() 默认容量是 integer的最大值，需自己指定容量，否则内存不够
         *
         * 一个线程池 code 7; max 50 , queue 50 ,100并发进来是怎么分配的
         * 7个会立即得到执行，50个会进入队列，再开13个进行执行。剩下的30个就使用拒绝策略
         * 如果不想抛弃还要执行， CallerRunsPolicy拒绝策略: 会执行run方法体。同步执行
         */
        // 3.创建一个原生线程池
        new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

        // 4.创建常用的4种线程池
        Executors.newCachedThreadPool();//core是1 ，其他所有线程都可以回收
        Executors.newFixedThreadPool(10);// core = max =10 ，固定大小，都不可以回收
        Executors.newScheduledThreadPool(10);//定时任务的线程池
        Executors.newSingleThreadExecutor();//core = max = 1,从队列中拿一个执行一个，相当于单线程保证任务执行顺序



    }

    /**
     * 1.测试callable
     */
    public static class MyCallable implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("任务执行");
            return 1;

        }
    }


}
